package com.erp.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.common.R;
import com.erp.dto.UserDto;
import com.erp.entity.User;
import com.erp.service.UserService;
import com.erp.utils.DigestsUtil;
import com.erp.utils.ValidateCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/info")
    public R<String> info(String token,HttpSession httpSession){
        String user = (String) httpSession.getAttribute("user");
        if (Objects.equals(user, token)){
            return R.success("",token);
        }else {
            return R.error("token错误");
        }
    }

    /**
     * 发送验证码 （已测试）
     *
     * @param user        用户实体
     * @param httpSession 用于接受生成的验证码
     * @return R
     */
    @PostMapping("/sendMsg")
    public R<String> sendMsg(@RequestBody User user, HttpSession httpSession) {
        log.info("发送验证码");

        String phone = user.getUsername();
        if (StringUtils.isNotEmpty(phone)) {
            //生成随机的4位验证码
            String code = ValidateCodeUtils.generateValidateCode(4).toString();
            log.info("code={}", code);
            //调用短信服务API完成发送短信任务
            //SMSUtils.sendMessage("","",phone,code);
            //保存验证码到Session
            httpSession.setAttribute(phone, code);
            //输出验证码到控制台
            System.out.println(httpSession.getAttribute(phone));

            return R.success("手机验证码短信发送成功");
        }
        return R.error("验证码发送失败");
    }


    /**
     * 用户注册 （已测试）
     *
     * @param map         用于接受用户名和验证码
     * @param httpSession 用于判断验证码是否正确
     * @return R
     */
    @PostMapping("/register")
    public R<UserDto> register(@RequestBody Map<String, String> map, HttpSession httpSession) {
        log.info("用户注册");

        return userService.register(map, httpSession);
    }

    /**
     * 用户登陆 （已测试）
     *
     * @param user 用户
     * @return 返回用户信息
     */
    @PostMapping("/login")
    public R<String> login(@RequestBody User user, HttpSession httpSession) {
        log.info("用户登录");

        //从SecurityUtils里边创建一个 subject
        Subject subject = SecurityUtils.getSubject();
        //执行登陆认证
        subject.login(new UsernamePasswordToken(user.getUsername(), user.getPassword()));
        User byUsername = userService.findByUsername(user.getUsername());

        if (byUsername.getStatus()==1){
            return R.error("账号被禁用");
        }

        //将用户id写回给httpSession
        httpSession.setAttribute("user", byUsername.getId());


        //登陆成功 返回用户详细信息
        return R.success(byUsername.getId().toString(),byUsername.getId().toString());
    }


    /**
     * 退出当前用户
     *
     * @param httpSession
     * @return
     */
    @PostMapping("/logout")
    public R<String> logout(HttpSession httpSession) {
        log.info("退出当前用户");

        httpSession.removeAttribute("user");
        //从SecurityUtils里边创建一个 subject
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return R.success("退出登录");
    }


    /**
     * 新增用户信息 （已测试）
     *
     * @param user 用户
     * @return R<String>
     */
    @PostMapping
    @RequiresPermissions(value = "SupperAdministrator:add")
    public R<String> save(@RequestBody User user) {
        log.info("管理员新增用户");

        return userService.add(user);
    }

    /**
     * 根据id查找用户 （已测试）
     * 超级管理员权限
     *
     * @param id 传入用户id
     * @return R<User>
     */
    @GetMapping("/{id}")
    public R<UserDto> findById(@PathVariable Long id) {
        log.info("管理员根据id查找用户");

        User user = userService.getById(id);
        if (user != null) {
            UserDto userDto = userService.userDtoCopy(user);
            return R.success(userDto);
        } else {
            return R.error("用户不存在");
        }
    }

    /**
     * 查询当前用户信息
     *
     * @param httpSession
     * @return
     */
    @GetMapping
    public R<UserDto> findCurrentUserById(HttpSession httpSession) {
        log.info("查询当前用户信息");

        Long userId = (Long) httpSession.getAttribute("user");
        User user = userService.getById(userId);
        UserDto userDto = userService.userDtoCopy(user);

        return R.success(userDto);
    }

    /**
     * 根据id删除用户 （已测试）
     * 超级管理员权限
     *
     * @param id 传入用户id
     * @return R<String>
     */
    @DeleteMapping
    @RequiresPermissions(value = "SupperAdministrator:delete")
    public R<String> deleteById(@RequestParam Long id) {
        log.info("管理员根据id删除用户");

        return userService.delete(id);
    }

    /**
     * 查询全部用户 （已测试）
     * 超级管理员权限
     *
     * @return R<List < User>>
     */
    @GetMapping("/list")
    @RequiresPermissions(value = "SupperAdministrator:list")
    public R<List<UserDto>> findAll() {
        log.info("管理员查询全部用户");

        List<User> list = userService.list();
        List<UserDto> userDtoList = new ArrayList<>();
        for (User user :list){
            UserDto userDto = userService.userDtoCopy(user);
            userDtoList.add(userDto);
        }
        return R.success(userDtoList);
    }

    /**
     * 修改当前用户信息 （已测试）
     *
     * @param user 用户
     * @return R<String>
     */
    @PutMapping
    public R<String> update(@RequestBody User user, HttpSession httpSession) {
        log.info("更新当前用户信息");

        //获取当前用户id
        user.setId((Long) httpSession.getAttribute("user"));
        if (userService.updateById(user)) {
            return R.success("更新成功");
        } else {
            return R.error("更新失败");
        }
    }

    /**
     * 根据id修改用户信息
     * 超级管理员权限
     *
     * @param user
     * @return
     */
    @PutMapping("/update")
    @RequiresPermissions(value = "SupperAdministrator:update")
    public R<String> updateById(@RequestBody User user) {
        log.info("管理员修改用户信息");
        if (user.getId()==1&&user.getStatus()==1){
            return R.error("不能禁用默认超级管理员");
        }
        userService.updateById(user);
        return R.success("修改成功");
    }


    /**
     * 分页查询 （已测试）
     *
     * @param page     页码
     * @param pageSize 每页显示条数
     * @return R<Page < User>>
     */
    @RequiresPermissions(value = "SupperAdministrator:list")
    @GetMapping("/page")
    public R<Page<User>> page(int page, int pageSize,String name) {
        log.info("用户分页查询");

        Page<User> userPage = new Page<>(page, pageSize);
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(User::getId);
        if (name!=null){
            lambdaQueryWrapper.like(User::getName,name);
        }
        userService.page(userPage, lambdaQueryWrapper);
        return R.success(userPage);
    }

    /**
     * 修改当前用户密码 （已测试）
     *
     * @param map         map集合封装旧密码 新密码 以及 确认密码
     * @param httpSession 用于获取当前用户id
     * @return
     */
    @PostMapping("/revisePassword")
    public R<String> revisePassword(@RequestBody Map map, HttpSession httpSession) {
        log.info("修改用户密码");

        //获取旧密码 新密码 以及确认密码
        String oldPassword = map.get("oldPassword").toString();
        String newPassword = map.get("newPassword").toString();
        String newPasswordAgain = map.get("newPasswordAgain").toString();
        //获取当前用户id
        Long userId = (Long) httpSession.getAttribute("user");
        System.out.println(userId);
        //根据id查询用户
        User user = userService.getById(userId);
        if (user == null) {
            return R.error("用户不存在");
        }
        //判断旧密码是否正确
        if (!user.getPassword().equals(DigestsUtil.sha1(oldPassword, user.getSalt()))) {
            return R.error("旧密码输入错误");
        }
        //确认新密码
        if (!newPassword.equals(newPasswordAgain)) {
            return R.error("确认密码错误");
        }
        //判断旧密码于新密码是否相同
        if (oldPassword.equals(newPassword)) {
            return R.error("旧密码于新密码相同");
        }
        //修改密码
        Map<String, String> stringMap = DigestsUtil.entryptPassword(newPassword);
        String salt = stringMap.get("salt");
        String password = stringMap.get("password");
        user.setSalt(salt);
        user.setPassword(password);
        userService.updateById(user);
        return R.success("密码更新成功");
    }


}
